/**
 * @file apdu_parser.h
 * @brief APDU解析器 - 专门负责APDU的解析
 * @details 本文件定义了104协议的APDU解析器功能，包括I格式、S格式、U格式APDU的
 *          解析、ASDU提取、APDU验证、序列号提取等核心功能。支持完整的APDU数据
 *          解析流程，确保解析的APDU数据符合104协议规范。
 * 
 * @author zyb
 * @date 2025-10-06
 * @version 1.0
 * 
 * @note 解析后的ASDU数据需要调用free_asdu()释放内存
 * @warning APDU解析时需要验证数据完整性，防止解析错误的数据
 * 
 * @see apdu_parser.c
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#ifndef APDU_PARSER_H
#define APDU_PARSER_H

#include "protocol_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== APDU解析函数 ==================== */

/**
 * @brief 解析APDU
 * @details 从字节流中解析APDU结构体。APDU包含启动字符、长度、控制域和可选数据。
 *          函数会验证启动字符、长度字段，然后解析控制域。对于I格式APDU，
 *          还会解析ASDU数据部分。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为APDU_MIN_LENGTH
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_APDU_INVALID_START: 无效启动字符
 *         - PROTOCOL_ERROR_APDU_INVALID_LENGTH: 无效长度
 * 
 * @note I格式APDU会解析ASDU数据，S格式和U格式APDU不包含ASDU数据
 * @warning 解析后的ASDU数据需要调用free_asdu()释放内存
 * 
 * @see apdu_t
 * @see APDU_START_CHAR
 * @see APDU_MIN_LENGTH
 * @see parse_asdu
 */
protocol_error_t parse_apdu(const uint8_t* buffer, size_t buffer_size, apdu_t* apdu);

/**
 * @brief 解析I格式APDU并提取序列号
 * @details 解析I格式APDU并提取发送和接收序列号。这是一个便捷函数，
 *          用于从I格式APDU中快速获取序列号信息。函数会验证APDU格式，
 *          然后从控制域中提取序列号。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param apdu APDU结构输出，不能为NULL
 * @param send_seq 发送序列号输出，不能为NULL
 * @param receive_seq 接收序列号输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 此函数是parse_apdu()的便捷版本，专门用于I格式APDU
 * @warning 解析后的ASDU数据需要调用free_asdu()释放内存
 * 
 * @see parse_apdu
 * @see is_i_format_apdu
 * @see extract_apdu_sequence_numbers
 */
protocol_error_t parse_i_format_apdu(const uint8_t* buffer, size_t buffer_size, apdu_t* apdu, uint16_t* send_seq, uint16_t* receive_seq);

/**
 * @brief 解析S格式APDU并提取序列号
 * @details 解析S格式APDU并提取接收序列号。这是一个便捷函数，
 *          用于从S格式APDU中快速获取序列号信息。函数会验证APDU格式，
 *          然后从控制域中提取接收序列号。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param apdu APDU结构输出，不能为NULL
 * @param receive_seq 接收序列号输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 此函数是parse_apdu()的便捷版本，专门用于S格式APDU
 * @warning S格式APDU不包含ASDU数据
 * 
 * @see parse_apdu
 * @see is_s_format_apdu
 */
protocol_error_t parse_s_format_apdu(const uint8_t* buffer, size_t buffer_size, apdu_t* apdu, uint16_t* receive_seq);

/**
 * @brief 解析U格式APDU并提取类型
 * @details 解析U格式APDU并提取U格式类型。这是一个便捷函数，
 *          用于从U格式APDU中快速获取控制类型信息。函数会验证APDU格式，
 *          然后从控制域中提取U格式类型。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param apdu APDU结构输出，不能为NULL
 * @param u_type U格式类型输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 此函数是parse_apdu()的便捷版本，专门用于U格式APDU
 * @warning U格式类型必须是有效的控制类型
 * 
 * @see parse_apdu
 * @see is_u_format_apdu
 * @see u_format_type_t
 */
protocol_error_t parse_u_format_apdu(const uint8_t* buffer, size_t buffer_size, apdu_t* apdu, u_format_type_t* u_type);

/* ==================== ASDU提取函数 ==================== */

/**
 * @brief 从APDU中提取ASDU
 * @details 从I格式APDU中提取ASDU数据。函数会验证APDU格式，
 *          然后解析ASDU数据部分。只有I格式APDU包含ASDU数据。
 * 
 * @param apdu APDU结构指针，不能为NULL
 * @param asdu ASDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 提取成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: ASDU数据不匹配
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 只有I格式APDU包含ASDU数据
 * @warning 提取后的ASDU数据需要调用free_asdu()释放内存
 * 
 * @see is_i_format_apdu
 * @see parse_asdu
 * @see free_asdu
 */
protocol_error_t extract_asdu_from_apdu(const apdu_t* apdu, asdu_t* asdu);

/* ==================== APDU验证函数 ==================== */

/**
 * @brief 验证APDU格式
 * @details 验证APDU的基本格式，包括启动字符、长度和控制域。
 *          这是一个基础验证函数，用于检查APDU的基本结构。
 * 
 * @param apdu APDU结构指针，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 验证成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_INVALID_START: 无效启动字符
 *         - PROTOCOL_ERROR_APDU_INVALID_LENGTH: 无效长度
 *         - PROTOCOL_ERROR_APDU_INVALID_CONTROL: 无效控制域
 * 
 * @note 验证包括启动字符、长度和控制域
 * @warning 此函数只验证基本格式，不验证序列号
 * 
 * @see is_apdu_length_valid
 * @see is_apdu_control_valid
 * @see APDU_START_CHAR
 */
protocol_error_t validate_apdu_format(const apdu_t* apdu);

/**
 * @brief 验证APDU序列号
 * @details 验证I格式APDU的发送和接收序列号是否符合期望值。
 *          用于检查协议会话的序列号同步状态。
 * 
 * @param apdu APDU结构指针，不能为NULL
 * @param expected_send_seq 期望的发送序列号
 * @param expected_receive_seq 期望的接收序列号
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 验证成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_SEQUENCE_ERROR: 序列号不匹配
 * 
 * @note 只有I格式APDU需要验证序列号
 * @warning 序列号必须在有效范围内（0-32767）
 * 
 * @see is_i_format_apdu
 * @see APDU_SEQUENCE_MASK
 */
protocol_error_t validate_apdu_sequence(const apdu_t* apdu, uint16_t expected_send_seq, uint16_t expected_receive_seq);

/* ==================== APDU清理函数 ==================== */

/**
 * @brief 释放APDU内存
 * @details 释放APDU结构中的动态分配内存，包括ASDU数据。
 *          用于清理APDU资源，防止内存泄漏。
 * 
 * @param apdu APDU结构指针，可以为NULL
 * 
 * @note 此函数是线程安全的
 * @warning 释放后APDU结构不再有效
 * 
 * @see apdu_t
 * @see free_asdu
 */
void free_apdu(apdu_t* apdu);

/**
 * @brief 释放ASDU内存
 * @details 释放ASDU结构中的动态分配内存，包括信息对象数据。
 *          用于清理ASDU资源，防止内存泄漏。
 * 
 * @param asdu ASDU结构指针，可以为NULL
 * 
 * @note 此函数是线程安全的
 * @warning 释放后ASDU结构不再有效
 * 
 * @see asdu_t
 * @see free_apdu
 */
void free_asdu(asdu_t* asdu);

/* ==================== 解析器辅助函数 ==================== */


#ifdef __cplusplus
}
#endif

#endif /* APDU_PARSER_H */
